/***********************************************************
 *  File_Name  : XJINIProfile.cpp
 *  File_Path   : 
 *  File_Encode : UTF8
 *  Description : INI配置文件读写类
 *  
 *  OS : Linux, UNIX,Windows,Other
 *  LastVersion  : 20130603
 *      
 *  Author      : LiXiujie(李秀杰)
 *  Date        : 2013-6-3
 *  Version     : 20130603
 *  Description : 
 *                
 *  Edit Author : 
 *  Edit Date   : 
 *  Version     : 
 *  Description :
 *                
 ***********************************************************/
#include "XJINIProfile.h"

namespace XJUtilClass {

XJINIProfile::XJINIProfile(bool bAutoTrimSpace) {
	// TODO Auto-generated constructor stub
	m_strLineEndSymbol = "\n";
	m_strCommentSymbol = ";";
	m_bTrim = bAutoTrimSpace;

}
XJINIProfile::XJINIProfile(const string &strFilePath, bool bAutoTrimSpace){
	m_strLineEndSymbol = "\n";
	m_strCommentSymbol = ";";
	m_bTrim = bAutoTrimSpace;
	ReadFile(strFilePath);
}

XJINIProfile::~XJINIProfile() {
	// TODO Auto-generated destructor stub
}

int XJINIProfile::AddItem(const XJINIProfileDataItem &item){
	m_strLastError.clear();
	unsigned int i = 0;
	for(i=0;i<m_veDataItems.size();i++){
		if (m_veDataItems[i].GetCate() == item.m_strCate &&
				m_veDataItems[i].GetName() == item.m_strName){
			m_veDataItems[i] = item;
			return 0;
		}
	}
	if (i == m_veDataItems.size())
		m_veDataItems.push_back(item);
	return 0;
}

int XJINIProfile::SetItem(const XJINIProfileDataItem &item){
	m_strLastError.clear();
	unsigned int i = 0;
	for(i=0;i<m_veDataItems.size();i++){
		if (m_veDataItems[i].GetCate() == item.m_strCate &&
				m_veDataItems[i].GetName() == item.m_strName){
			m_veDataItems[i] = item;
			return 0;
		}
	}
	if (i == m_veDataItems.size())
		m_veDataItems.push_back(item);
	return 0;
}

int XJINIProfile::DelItem(const string & strItemName){
	m_strLastError.clear();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == "Default" && item.m_strName == strItemName){
			it = m_veDataItems.erase(it);
			return 0;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return -1;
}

int XJINIProfile::DelItem(const string & strCategoryName, const string & strItemName){
	m_strLastError.clear();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == strCategoryName && item.m_strName == strItemName){
			it = m_veDataItems.erase(it);
			return 0;;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return -1;
}

XJINIProfileDataItem & XJINIProfile::GetItem(const string & strItemName){
	m_strLastError.clear();
	m_itemNull = XJINIProfileDataItem();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == "Default" && item.m_strName == strItemName){
			return item;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return m_itemNull;
}

XJINIProfileDataItem & XJINIProfile::GetItem(const string & strCategoryName, const string & strItemName){
	m_strLastError.clear();
	m_itemNull = XJINIProfileDataItem();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == "Default" && item.m_strName == strItemName){
			return item;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return m_itemNull;
}

string &XJINIProfile::GetItemValue(const string & strItemName){
	m_strLastError.clear();
	m_itemNull = XJINIProfileDataItem();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == "Default" && item.m_strName == strItemName){
			return item.m_strValue;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return m_itemNull.m_strValue;
}

string &XJINIProfile::GetItemValue(const string & strCategoryName, const string & strItemName){
	m_strLastError.clear();
	m_itemNull = XJINIProfileDataItem();
	vector<XJINIProfileDataItem >::iterator it = m_veDataItems.begin();
	while(it != m_veDataItems.end()){
		XJINIProfileDataItem &item = *it;
		if (item.m_strCate == strCategoryName && item.m_strName == strItemName){
			return item.m_strValue;
		}
		it++;
	}
	m_strLastError = "Not found!";
	return m_itemNull.m_strValue;
}
string &XJINIProfile::GetV(const string & strItemName){
	return GetItemValue(strItemName);
}
string &XJINIProfile::GetV(const string & strCategoryName, const string & strItemName){
	return GetItemValue(strCategoryName, strItemName);
}
int XJINIProfile::GetCategoryNameList(vector<string >& veCategoryName){
	unsigned int i,j;
	bool bHas = false;
	for(i=0;i<m_veDataItems.size();i++){
		bHas = false;
		for(j=0;j<veCategoryName.size();j++){
			if(m_veDataItems[i].m_strCate == veCategoryName[j]){
				bHas = true;
				break;
			}
		}
		if(!bHas){
			veCategoryName.push_back(m_veDataItems[i].m_strCate);
		}
	}
	return 0;
}
int XJINIProfile::GetItemNameList(vector<string >& veItemName, const string & strCategoryName){
	unsigned int i,j;
	bool bHas = false;
	for(i=0;i<m_veDataItems.size();i++){
		if (m_veDataItems[i].m_strCate != strCategoryName){
			continue;
		}
		bHas = false;
		for(j=0;j<veItemName.size();j++){
			if(m_veDataItems[i].m_strName == veItemName[j]){
				bHas = true;
				break;
			}
		}
		if(!bHas){
			veItemName.push_back(m_veDataItems[i].m_strName);
		}
	}
	return 0;
}
int XJINIProfile::ReadFile(const string &strFilePath){
	m_strLastError.clear();
	ifstream  fsINI(strFilePath.c_str());
	if (!fsINI.is_open()){
		m_strLastError = "ReadFile load file error.";
		m_strLastError += strerror(errno);
		m_strLastError += ".";
		m_strLastError += strFilePath;
		return -1;
	}
	string strCateName;
	string strItemName, strItemValue;
	string strDesc;
	strCateName = "Default";
	while(fsINI.peek() != EOF)
	{
		char szLineData[1024] = { 0 };
		char szTmp[1024] = { 0 };
		fsINI.getline(szLineData, 1024);
		if (strlen(szLineData) > 0 && szLineData[strlen(szLineData) - 1] == '\n'){
			szLineData[strlen(szLineData) - 1] = '\0';
		}
		if (strlen(szLineData) > 0 && szLineData[strlen(szLineData) - 1] == '\r'){
			szLineData[strlen(szLineData) - 1] = '\0';
		}
		if (strlen(szLineData) == 0){
			continue;
		}

		char *pChar = strstr(szLineData, m_strCommentSymbol.c_str());
		if (pChar >= szLineData){
			memset(szTmp, 0, sizeof(szTmp));
			if (pChar+1 <= szLineData+strlen(szLineData)){
				strcpy(szTmp, pChar+1);
			}
			strDesc = szTmp;
			memset(szTmp, 0, sizeof(szTmp));
			strncpy(szTmp, szLineData, pChar-szLineData);
			memset(szLineData, 0, sizeof(szLineData));
			strcpy(szLineData, szTmp);
		}

		char *pChar1, *pChar2, *pChar3;
		pChar1 = strstr(szLineData, "[");
		pChar2 = strstr(szLineData, "]");
		pChar3 = strstr(szLineData, "=");
		if (pChar1 ==  szLineData && pChar2 - 1 >= pChar1){
			memset(szTmp, 0, sizeof(szTmp));
			if (pChar1+1 <= szLineData+strlen(szLineData)){
				strncpy(szTmp, pChar1+1, pChar2-pChar1-1);
			}
			strCateName = szTmp;
			strDesc = "";
		}else if (pChar3 >= szLineData){
			memset(szTmp, 0, sizeof(szTmp));
			strncpy(szTmp, szLineData, pChar3 - szLineData);
			strItemName = szTmp;
			memset(szTmp, 0, sizeof(szTmp));
			if (pChar3+1 <= szLineData+strlen(szLineData)){
				strcpy(szTmp, pChar3+1);
			}
			strItemValue = szTmp;
			if (m_bTrim){
				TrimHeadTail(strItemName);
				TrimHeadTail(strItemValue);
			}
			XJINIProfileDataItem item;
			item.SetCate(strCateName);
			item.SetName(strItemName);
			item.SetValue(strItemValue);
			item.SetDesc(strDesc);
			AddItem(item);
		}
	}
	fsINI.close();
	return 0;
}

int XJINIProfile::WriteFile(const string &strFilePath){
	int nRet = 0;
	m_strLastError.clear();
	ofstream  fsINI(strFilePath.c_str(), ios::trunc);
	if (!fsINI.is_open()){
		m_strLastError = "ReadFile load file error.";
		m_strLastError += strFilePath;
		return -1;
	}
	unsigned i,j;
	string strCateName;
	vector<string > veCateNames;
	for (i=0;i<m_veDataItems.size();i++){
		XJINIProfileDataItem &item = m_veDataItems[i];
		strCateName = item.GetCate();
		for (j=0;j<veCateNames.size();j++){
			if (veCateNames[j].compare(item.GetCate()) == 0){
				break;
			}
		}
		if (j == veCateNames.size()){
			veCateNames.push_back(strCateName);
		}else{
			continue;
		}
	}
	string strLineData;
	for (i=0;i<veCateNames.size();i++){
		strLineData = "";
		strLineData = strLineData+"["+veCateNames[i]+"]"+m_strLineEndSymbol;
		fsINI.write(strLineData.c_str(), strLineData.size());
		for (j=0;j<m_veDataItems.size();j++){
			XJINIProfileDataItem &item2 = m_veDataItems[j];
			if (item2.GetCate().compare(veCateNames[i]) == 0){
				if (item2.GetDesc().size()){
					strLineData = "";
					strLineData = strLineData+m_strCommentSymbol+item2.GetDesc()+m_strLineEndSymbol;
					fsINI.write(strLineData.c_str(), strLineData.size());
				}
				strLineData = "";
				strLineData = strLineData+item2.GetName()+"="+item2.GetValue()+m_strLineEndSymbol;
				fsINI.write(strLineData.c_str(), strLineData.size());
			}
		}
	}
	fsINI.flush();
	fsINI.close();
	return nRet;
}

string &XJINIProfile::GetLastError(){
	return m_strLastError;
}
void XJINIProfile::Clear(){
	m_veDataItems.clear();
}

string &XJINIProfile::TrimHeadTail(string &strSource, const char ch){
	string strTrim(1, ch);
	strSource.erase(strSource.find_last_not_of(strTrim)+1); // 标准string +1
	strSource.erase(0, strSource.find_first_not_of(strTrim));
	return strSource;
}
void XJINIProfile::SetAutoTrimSpace(bool bTrim){
	m_bTrim = true;
}

} /* namespace XJClassUtil */
